﻿using Microsoft.Extensions.DependencyInjection;
using Modules.System.User;
using PetaPoco;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Entity;
using PmSoft.Repositories;
using static Modules.Project.ProjectConstants;

namespace Modules.Payroll.Repositories
{
    [UseDI(ServiceLifetime.Scoped)]
    public class WagePayrollRepository : Repository<WagePayroll, DefaultDbContext>
    {
        private readonly IApplicationContext applicationContext;

        public WagePayrollRepository(DefaultDbContext dbContext, IApplicationContext applicationContext) : base(dbContext, applicationContext)
        {
            this.applicationContext = applicationContext;
        }

        public IPagedList<WagePayroll> GetWagePayrolls(WagePayrollQuery query, int pageIndex, int pageSize)
        {
            Sql sql = Sql.Builder.Select("wage_payroll.id").From("wage_payroll")
                    .InnerJoin("corp as c").On("wage_payroll.corp_id = c.corp_id");

            #region 主管单位数据权限

            if (applicationContext.CurrentUser is IDeptUser deptUser && !deptUser.IsSuperAdministrator())
            {
                sql.InnerJoin("project as prj").On($"wage_payroll.project_id=prj.project_id and prj.is_deleted=0 and prj.industry_type=@0 ", deptUser.IndustryType);
                if (deptUser.Level == AdministrativeLevel.City)
                    sql.Append($" and prj.city_code={deptUser.CityCode}");
                if (deptUser.Level == AdministrativeLevel.Area)
                    sql.Append($" and prj.area_code={deptUser.AreaCode}");
            }

            #endregion 主管单位数据权限

            if (query.WageStatus.HasValue)
                sql.Where("wage_payroll.wage_status=@0", query.WageStatus);
            if (query.ProjectId.HasValue)
                sql.Where("wage_payroll.project_id=@0", query.ProjectId);
            if (query.CorpId.HasValue)
                sql.Where("wage_payroll.corp_id=@0", query.CorpId);
            if (query.Month.HasValue)
                sql.Where("wage_payroll.month=@0", query.Month);
            if (query.CorpIds != null)
                sql.Where("wage_payroll.corp_id in(@0)", query.CorpIds);
            sql.OrderBy("wage_payroll.create_time DESC");
            return GetPagingEntities(pageSize, pageIndex, sql);
        }

        /// <summary>
        /// 获取待发放工资单
        /// </summary>
        /// <returns></returns>
        public IEnumerable<WagePayroll> GetWaitingWagePayrolls()
        {
            int areaVersion = EntityCacheService.GetAreaVersion("WageStatus", PayrollConstants.代发状态.待发放);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"WagePayrollsByWageStatus:{PayrollConstants.代发状态.待发放}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("id")
                .From("wage_payroll")
                .Where("wage_status=@0 and has_submit=1", PayrollConstants.代发状态.待发放);
                sql.OrderBy("id ");
                return sql;
            });
        }

        public WagePayroll? GetWagePayrollByMaxSerialNumber(DateTime time, int projectId)
        {
            Sql sql = Sql.Builder.Select("id").From("wage_payroll");
            sql.Where("DATE(create_time)=@0", time.Date);
            sql.Where("project_id=@0", projectId);
            sql.OrderBy("serial_number desc");
            var id = DbContext.FirstOrDefault<int>(sql);
            if (id == 0)
                return null;
            return Get(id);
        }

        /// <summary>
        /// 根据项目及参建单位查询总支出额
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="corpId"></param>
        /// <returns></returns>
        public decimal GetSumWagePayrollsSuccessfulAmount(int projectId, int corpId)
        {
            Sql sql = Sql.Builder.Select("SUM(IFNULL( successful_amount,0))").From("wage_payroll").Where("project_id=@0 and corp_id=@1", projectId, corpId);
            return DbContext.ExecuteScalar<decimal>(sql);
        }

        public IEnumerable<WagePayroll> GetWagePayrollsByProjectIdsAndMonth(IEnumerable<int> projectIds, string month)
        {
            if (projectIds == null || !projectIds.Any())
                return Enumerable.Empty<WagePayroll>();
            Sql sql = Sql.Builder.Select("id").From("wage_payroll").Where("project_id in(@0) AND month =1", projectIds, month);
            var ids = DbContext.FetchFirstColumn<int>(sql);

            return PopulateEntitiesByEntityIds(ids);
        }

        public WagePayroll? GetWagePayrollByCode(string code)
        {
            Sql sql = Sql.Builder.Select("id").From("wage_payroll").Where("code = @0", code);

            var id = DbContext.FirstOrDefault<int>(sql);
            return Get(id);
        }

        /// <summary>
        /// 通过代发批次号获取工资单信息
        /// </summary>
        /// <param name="batchNo"></param>
        /// <returns></returns>
        public WagePayroll? GetWagePayrollByBatchNo(string batchNo)
        {
            Sql sql = Sql.Builder.Select("id").From("wage_payroll").Where("batch_no = @0", batchNo);
            var id = DbContext.FirstOrDefault<int>(sql);
            return Get(id);
        }
    }
}